

import requests as req

from Decorator import log_execution, logger_gen

logger = logger_gen.get_logger(__name__)


class ElasticRequest:
    def __init__(self, hosts, ports, http_auth, timeout):
        self.hosts = hosts
        self.ports = ports
        self.auth = http_auth
        self.timeout = timeout

        self.__url = self.__get_available_url()
        self.__skip_flag = [{"times": 0, "skip_times": 0} for _ in range(len(hosts))]
        self.addr = self.__get_url

        self.__get_es_version()

    def __get_available_url(self):
        while True:
            for host_index, (host, port) in enumerate(zip(self.hosts, self.ports)):
                if self.__skip_flag[host_index]['skip_times'] > 0:
                    self.__skip_flag[host_index]['skip_times'] -= 1
                    continue

                try:
                    req.get("http://{}:{}/_cat/health".format(host, port), auth=self.auth, timeout=10, verify=False)

                except Exception as e:
                    logger.warning("{} > 节点 {}:{} 连接失败，异常信息 {}".format(self.__get_available_url.__name__, host, port, e))
                    self.__skip_flag[host_index]['skip_times'] += 2 ** self.__skip_flag[host_index]['times']
                    self.__skip_flag[host_index]['times'] += 1

                else:
                    yield "http://{}:{}".format(host, port)

            if all([dct['times'] > 5 for dct in self.__skip_flag]):
                logger.error("{} > 集群连接点均不可用 {}".format(self.__get_url.__name__, ",".join(['{}:{}'.format(host, port) for host, port in zip(self.hosts, self.ports)])))
                yield None
                break

    def __get_url(self):
        return next(self.__url)

    @log_execution(logger)
    def __get_es_version(self):
        addr = self.addr()
        try:
            response = req.get(url="{}/_cat/nodes?h=version&format=json".format(addr), auth=self.auth)
            logger.debug("def __get_es_version > {}".format(response.json()))

        except req.RequestException as e:
            logger.warning("def __get_es_version > 检查集群版本失败，异常信息 {}".format(e))
            self.version = "noVersion"

        else:
            self.version = response.json().pop()['version']

    def __get_cat_api_requset_parameter(self, format='json', pretty='true', human='true', **kwargs):
        es_parameter = ''

        kwargs['format'], kwargs['pretty'], kwargs['human'] = kwargs.get('format', format), kwargs.get('pretty', pretty), kwargs.get('human', human)

        # 目前常用的就这两个，有其他的就再加
        comma_separated_list = ['h', 'index']

        for id, (key, value) in enumerate(kwargs.items()):
            logger.debug(" def __get_requset_parameter > es_parameter 参数变化 {}".format(es_parameter))
            param_template = "?{}={}" if id == 0 else "&{}={}"

            if key in comma_separated_list:
                es_parameter = "{}{}".format(es_parameter, param_template.format(key, ",".join(value)))
                continue
            es_parameter = "{}{}".format(es_parameter, param_template.format(key, value))

        return es_parameter


if __name__ == '__main__':
    hosts = ['ip1', 'ip2', 'ip3', 'ip4']
    ports = ['port' for _ in range(len(hosts))]
    elastic_client = ElasticRequest(hosts, ports, ('user', 'pwd'), 300)